/*
*  imageHash.cpp
*/
#include <jni.h>

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc_c.h>


using namespace cv;

extern "C"
jint Java_com_eltech_battleofrunes_compareTwoPic_calcDist(JNIEnv* env, jobject thiz, jint object_w, jint object_h, jintArray objectArray, jint image_w, jint image_h, jintArray imageArray)
{
	// Object
	// Get the data pointer.
	jint* _ob = env->GetIntArrayElements(objectArray, 0);
	// Build the Mat structure for input data
	Mat obMat(object_h, object_w, CV_8UC4, (unsigned char *)_ob);

	// Image
	// Get the data pointer.
	jint* _im = env->GetIntArrayElements(imageArray, 0);
	// Build the Mat structure for input data
	Mat imMat(image_h, image_w, CV_8UC4, (unsigned char *)_im);

	// Convert Mat to IplImage
	IplImage obIpl = obMat;
	IplImage *pObIpl = &obIpl;
	IplImage imIpl = imMat;
	IplImage *pImIpl = &imIpl;

	// ��� ��� ������
	IplImage *res = 0, *gray = 0, *bin = 0;

	res = cvCreateImage( cvSize(8, 8), pObIpl->depth, pObIpl->nChannels);
	gray = cvCreateImage( cvSize(8, 8), IPL_DEPTH_8U, 1);
	bin = cvCreateImage( cvSize(8, 8), IPL_DEPTH_8U, 1);

	// ��������� ��������
	cvResize(pObIpl, res);
	// ��������� � �������� ������
	cvCvtColor(res, gray, CV_BGR2GRAY);
	// ��������� �������
	CvScalar average = cvAvg(gray);
	// ������� �������� ����������� ������������ ��������
	// ��� ����� ������������� ��������� ���������������
	cvThreshold(gray, bin, average.val[0], 255, CV_THRESH_BINARY);

	// �������� ���
	unsigned long hashO = 0;

	int i=0;
	// ����������� �� ���� �������� �����������
	for( int y=0; y<bin->height; y++ ) {
		uchar* ptr = (uchar*) (bin->imageData + y * bin->widthStep);
		for( int x=0; x<bin->width; x++ ) {
			// 1 �����
			if(ptr[x]){
				// hash |= 1<<i;  // warning C4334: '<<' : result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
				hashO |= 1<<i;
			}
			i++;
		}
	}

	// ����������� �������
	cvReleaseImage(&res);
	cvReleaseImage(&gray);
	cvReleaseImage(&bin);

	// ��� ��� �����������
	res = cvCreateImage( cvSize(8, 8), pImIpl->depth, pImIpl->nChannels);
	gray = cvCreateImage( cvSize(8, 8), IPL_DEPTH_8U, 1);
	bin = cvCreateImage( cvSize(8, 8), IPL_DEPTH_8U, 1);

	// ��������� ��������
	cvResize(pImIpl, res);
	// ��������� � �������� ������
	cvCvtColor(res, gray, CV_BGR2GRAY);
	// ��������� �������
	average = cvAvg(gray);
	// ������� �������� ����������� ������������ ��������
	// ��� ����� ������������� ��������� ���������������
	cvThreshold(gray, bin, average.val[0], 255, CV_THRESH_BINARY);

	// �������� ���
	unsigned long hashI = 0;

	i=0;
	// ����������� �� ���� �������� �����������
	for( int y=0; y<bin->height; y++ ) {
		uchar* ptr = (uchar*) (bin->imageData + y * bin->widthStep);
		for( int x=0; x<bin->width; x++ ) {
			// 1 �����
			if(ptr[x]){
				hashI |= 1<<i;
			}
			i++;
		}
	}

	// ����������� �������
	cvReleaseImage(&res);
	cvReleaseImage(&gray);
	cvReleaseImage(&bin);

	// ���������� ���������� ��������
	int dist = 0;
	unsigned long val = hashO ^ hashI;
	// Count the number of set bits
	while(val)
	{
		++dist;
		val &= val - 1;
	}

	return dist;
}
